#pragma once

#include <IwGeomFVec2.h>
#include "Sprite.h"
#include "FVec2RingBuffer.h"
#include "TouchArea.h"
#include "OBB.h"
#include "Dock.h"

struct arc_length_lookup_node {
	float arc_length;
	float t;
};

#define NUM_SAMPLES 5

namespace ShipState {
	enum Enum {
		UNUSED, // the ship isnot used
		ACTIVE_IN, // the ship is active and has to be moved to a dock
		DOCKING, // the ship is currently in the process of docking
		CRASHED, // the ship crashed
		ACTIVE_OUT, // the ship is active and has to be moved outside the screen
	};
}

class ScoreSystem;

class Ship {

public:
	explicit Ship();
	
	void Load( ScoreSystem* score_system );
	void Unload();
	void Update( float dt, bool path_editing_active );
	void Draw();
	
	bool ReachedMaxNodes() const;
	
	bool OutsideScreen() const;
	
	CIwFVec2 GetPos() const;
	
	// returns true if the touch with the given id was in
	// the area of the ship
	bool TouchInArea( uint touch );
	
	void InvertMovement( const CIwFVec2& dir, const CIwFVec2& normal );
	
	const OBB& GetOBB() const;
	
	bool WasAtDock() const;
	bool IsDocking() const;
	
	void StartDocking( const Dock& dock );
	
	bool IsActive() const;
	
	void Start( DockType::Enum target_dock, CIwFVec2 p1, CIwFVec2 p2 );
	
	CIwFVec2 GetCurrentDir() const;
	
	void Disable();
	
	DockType::Enum GetTargetDock() const;
	
	void Crashed();
	
	bool HasCrashed() const;
	
private:
	void PrecalcArcLengthLookup(  );

	Sprite m_yellow_boat;
	Sprite m_red_boat;
	Sprite m_arrow_left;
	Sprite m_arrow_right;
	
	Sprite m_unload_progress_bg;
	Sprite m_unload_progress;
	
	float m_flicker_progress;

	FVec2RingBuffer m_nodes_ring;
	FVec2RingBuffer m_lines_ring;
	arc_length_lookup_node m_arc_length_lookup[NUM_SAMPLES + 2];
	TouchArea m_touch_area;
	Sprite *m_sprite;
	OBB m_obb;
	CIwSVec2 m_arrow_pos;
	CIwFVec2 m_last_pos;
	CIwFVec2 m_pos;
	CIwFVec2 m_last_orientation;
	CIwFVec2 m_orientation;
	CIwFVec2 m_dock_pos;
	CIwFVec2 m_dock_orientation;
	ScoreSystem* m_score_system;
	float m_arc_distance;
	float m_t;
	bool m_active;
	bool last_add_tmp;
	ShipState::Enum m_state;
	float m_docking_time;
	float m_last_line_node_time;
	DockType::Enum m_target_dock;
};